import 'dart:isolate';
import 'dart:math';

import 'package:flutter_test/flutter_test.dart';
import 'package:im_app/im/socket/dto/business/RpcData.dart';
import 'package:logger/logger.dart';

void main() {


  test("test isolate", () async {
    _IsoateTest test = _IsoateTest();
    await test.start();
    // test.listen();
    for (var i=0; i<10; i++) {
      RpcData rpcData = RpcData.data("path$i", '$i', '$i');
      var result = await test.sendData(rpcData, (){});
      print("result $result.path");
    }
    await Future.delayed(Duration(seconds: 10));
    test.close();
  });


}

class _IsoateTest {

  var _logger = Logger(
    printer: PrettyPrinter(),
  );

  late Isolate _isolate;
  late SendPort _isolateSendPort;

  Future<void> start() async {
    ReceivePort receivePort = new ReceivePort();
    _isolate = await Isolate.spawn(doRunner,  _IsloateInitData('adfafaf', receivePort.sendPort));
    _isolateSendPort = await receivePort.first as SendPort;
    _logger.i("websocket client start!!!");
  }

  Future<RpcData> sendData(RpcData rpcData, Function function) async {
    ReceivePort sendDataReceivePort = new ReceivePort();
    try {
      assert(_isolateSendPort != null, "newIceSP must be not null");
      _isolateSendPort.send(_SendData.from(rpcData: rpcData,
          decodeFunction: function,
          sendPort: sendDataReceivePort.sendPort));
      // newIceSP.send(sendDataReceivePort.sendPort);
      _logger.i("send message path: ${rpcData.path}");
      String r = await sendDataReceivePort.first.timeout(Duration(seconds: 10)) as String;
      // RpcData result = await sendDataReceivePort.first.timeout(Duration(seconds: 10)) as RpcData;
      // return result;
      rpcData.path = r;
      return rpcData;
    } finally {
      sendDataReceivePort.close();
    }

  }

  void close() {
    _isolate?.kill();
  }
}

Future<void> doRunner(_IsloateInitData isloateInitData) async {
  var newIceRP = ReceivePort();
  isloateInitData.sendPort.send(newIceRP.sendPort);

  newIceRP.listen((dynamic message) {
    switch (message) {
      case _SendData():
        _SendData sendData = message;
        sendData.sendPort?.send("success");
      case int():

    }
  });
}

class _IsloateInitData {
  final String _webSocketUrl;
  final SendPort _sendPort;

  _IsloateInitData(this._webSocketUrl, this._sendPort);

  String get webSocketUrl => _webSocketUrl;
  SendPort get sendPort => _sendPort;
}

class _InnerData {
  final _SendData _message;
  final SendPort? _sendPort;

  _InnerData(this._message, this._sendPort);

  _SendData get message => _message;
  SendPort? get sendPort => _sendPort;
}

class _SendData {
  final RpcData rpcData;
  final Function decodeFunction;
  SendPort? sendPort;

  _SendData(this.rpcData, this.decodeFunction);

  _SendData.from({required this.rpcData, required this.decodeFunction, this.sendPort});
}